home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / lisp / oobr / tree-nx / TreeView.m < prev   
Encoding:
Text File  |  1995-03-25  |  6.4 KB  |  275 lines

  1.  
  2. #import "TreeView.h"
  3. #import "TreeButton.h"
  4. #import "NamedTree.h"
  5. #import "Line.h"
  6.  
  7. // constants to determine how the buttons are laid out
  8. #define BUTTONWIDTH    155.0
  9. #define BUTTONHEIGHT     24.0
  10. #define VERTSPACING       8.0
  11. #define HORIZSPACING     40.0
  12.  
  13. @implementation TreeView
  14.  
  15. - initFrame:(const NXRect *)frameRect
  16. {
  17.   [super initFrame:frameRect];
  18.   [self setAutosizing:(unsigned int) (NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE)];
  19.  
  20.   currentButton = nil;
  21.   lineList = nil;
  22.   priorButton = nil;
  23.   [selectedField setNextText: selectedField];
  24.   [selectedField setPreviousText: selectedField];
  25.   currScale  = 1.0;
  26.  
  27.   [self registerForDragging];
  28.   [self setOpaque:YES];
  29.  
  30.   return self;
  31. }
  32.  
  33. - buildTreeFromNode:aNode bottom:(double)ybot
  34.         top:(double)ytop atX:(double)xpos parent:(NXPoint *)pos
  35. {    // add a button representing the node to the View
  36.     // This method is recursive.
  37.     NXRect butFrame = {{(xpos + HORIZSPACING),
  38.             (ybot + (ytop - ybot) / 2 - BUTTONHEIGHT / 2)},
  39.             {BUTTONWIDTH, BUTTONHEIGHT}};
  40.     id newButton = [[[TreeButton alloc] initFrame:&butFrame]
  41.             setTreeNode:aNode];
  42.     id kid, kids = [aNode branches];
  43.     int numBranches = [kids count];
  44.     int i, treeWidth; double diff, accum = ybot;
  45.     NXPoint myCenter = {(NX_X(&butFrame)),
  46.                 (NX_Y(&butFrame) + BUTTONHEIGHT / 2)};
  47.     id newLine;
  48.     
  49.     [newButton setTitle:[aNode label]];
  50.     [self addSubview:newButton];
  51.     // line to parent:
  52.     if (pos) {    // NULL if root, so no line
  53.         NXPoint parentRight = { pos->x + BUTTONWIDTH, pos->y };
  54.         newLine = [[Line alloc] init];
  55.         [newLine setStart:&parentRight end:&myCenter];
  56.         [lineList addObject:newLine];
  57.     }
  58.     // now add any children and the lines to them.
  59.     for (i=numBranches - 1; i >= 0; i--) { // loop isn't entered if no kids.
  60.         kid = [kids objectAt:i];
  61.         treeWidth = [kid width];
  62.         diff = (treeWidth * (BUTTONHEIGHT + VERTSPACING));
  63.         [self buildTreeFromNode:kid bottom:accum
  64.                 top:(accum + diff + VERTSPACING)
  65.                 atX:(xpos + BUTTONWIDTH + HORIZSPACING)
  66.                 parent:&myCenter];
  67.         accum += diff;
  68.     }
  69.     return self;
  70. }
  71.  
  72. - attachTree:aTree
  73. {
  74.     int treeWidth = [aTree width];
  75.     int treeDepth = [aTree depth];
  76.     double height = (treeWidth * (BUTTONHEIGHT + VERTSPACING) + VERTSPACING);
  77.     double width  = (treeDepth * (BUTTONWIDTH + HORIZSPACING) + HORIZSPACING);
  78.     
  79.     treeRoot = aTree;
  80.     if (lineList) [[lineList freeObjects] free];
  81.     lineList = [[List alloc] init];
  82.     // resize the View to accomodate the Buttons
  83.     [self sizeTo:width :height];
  84.     [self buildTreeFromNode:aTree bottom:0.0 top:height atX:0.0 parent:NULL];
  85.  
  86.     return self;
  87. }
  88.  
  89. - drawSelf:(NXRect *)rects :(int)rectCount      // standard rendering method
  90. {
  91.     NXColor color = [[self window] backgroundColor];
  92.  
  93.     if (NXEqualColor(color, NX_COLORLTGRAY))
  94.        color = NX_COLORDKGRAY;
  95.  
  96.     // PSsetgray(NX_DKGRAY);
  97.     NXSetColor(color);
  98.     NXRectFill(&bounds);
  99.     // PSsetgray(NX_BLACK);
  100.     NXSetColor(NX_COLORBLACK);
  101.     PSsetlinewidth(2.0);
  102.  
  103.     [lineList makeObjectsPerform:@selector(render)];
  104.     [[self subviews] makeObjectsPerform:@selector(display)];
  105.     return self;
  106. }
  107.  
  108. - scale:sender
  109. {
  110.   id popUp = [sender window];
  111.   short index = [popUp indexOfItem:[popUp selectedItem]];
  112.   //                   25%   50%  75%  100%  125%  150%  200%  SizeToFit
  113.   //                   0     1      2     3     4     5     6    7
  114.   float factors[] = {0.25,  0.50, 0.75,  1.0, 1.25, 1.50, 2.0, 0.20};
  115.   NXPoint center;
  116.   NXCoord scale = factors[index];
  117.  
  118.   // Initialize width and height bounds when view is not scaled.
  119.   if (currScale == 1.0)
  120.     {
  121.       origWidth = NX_WIDTH(&bounds);
  122.       origHeight = NX_HEIGHT(&bounds);
  123.     }
  124.  
  125.   // Remember the center to we can reset it after the scaling.
  126.   center.x = NX_X(&bounds) + NX_WIDTH(&bounds) / 2;
  127.   center.y = NX_Y(&bounds) + NX_HEIGHT(&bounds) / 2;
  128.  
  129.   // Scale the view to its new size
  130.   if (index == 3) // 100% (Normal Size)
  131.     {
  132.      [self setDrawSize:origWidth :origHeight];
  133.      currScale  = 1.0;
  134.     }
  135.   else
  136.     {
  137.       currScale *= scale;
  138.       [self setDrawSize:NX_WIDTH(&bounds) / currScale
  139.                        :NX_HEIGHT(&bounds) / currScale];
  140.     }
  141.  
  142.   // Reset the center point
  143.   [self setDrawOrigin:center.x - NX_WIDTH(&bounds) / 2
  144.               :center.y - NX_HEIGHT(&bounds) / 2];
  145.  
  146.   // Ensure that selected button, if any, is visible.
  147.   [self displayBut:currentButton];
  148.  
  149.   [self update];
  150.  
  151.   return self;
  152. }
  153.  
  154. - setCurrentButton:but
  155. {
  156.   if (but)
  157.     {
  158.       priorButton = currentButton;
  159.       if (priorButton)
  160.     {
  161.       [priorButton setType:NX_MOMENTARYPUSH];
  162.       [priorButton setState:0];
  163.     }
  164.       currentButton = but;
  165.       [currentButton setType:NX_ONOFF]; [currentButton setState:1];
  166.       // [selectedField setStringValueNoCopy: [but title]];
  167.     }
  168.   return but;
  169. }
  170.  
  171. - setCurrButtonByName:sender
  172. {
  173.   id currBut = [self getButByName:[sender stringValue]];
  174.  
  175.   [self displayBut:[self setCurrentButton:currBut]];
  176.   [treeRoot act:currBut];
  177.   return currBut;
  178. }
  179.  
  180. - getButByName:(const char*)name
  181. {
  182.   id butList = [self subviews];
  183.   id but = nil;
  184.   id currBut = nil;
  185.   int i = 0;
  186.  
  187.   while (!currBut && (but = [butList objectAt:i++]))
  188.     {
  189.       if (!strcmp([but title], name))
  190.     currBut = but;
  191.     }
  192.   return currBut;
  193. }
  194.  
  195. - displayButByName:sender
  196. {
  197.   id but = [self getButByName:[sender stringValue]];
  198.  
  199.   if (but)
  200.     [self displayBut:but];
  201.   return but;
  202. }
  203.  
  204. - displayBut:but
  205. {
  206.   NXRect butRect;
  207.  
  208.   if (but)
  209.     {
  210.       [[but getBounds:&butRect] convertRectToSuperview:&butRect];
  211.       [self scrollRectToVisible:&butRect];
  212.     }
  213.   return self;
  214. }
  215.  
  216. @end
  217.  
  218.  
  219.  
  220. // Color dragging support
  221.  
  222. BOOL includesType(const NXAtom *types, NXAtom type)
  223. {
  224.     if (types)
  225.       while (*types)
  226.     if (*types++ == type)
  227.       return YES;
  228.     return NO;
  229. }
  230.  
  231. @implementation TreeView(Drag)
  232.  
  233. - registerForDragging
  234. {
  235.  [self registerForDraggedTypes:&NXColorPboardType count:1];
  236.  return self;
  237. }
  238.  
  239. - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
  240. {
  241.   NXDragOperation sourceMask = [sender draggingSourceOperationMask];
  242.   Pasteboard *pboard = [sender draggingPasteboard];
  243.  
  244.   return ((includesType([pboard types], NXColorPboardType))
  245.        ? NX_DragOperationGeneric : NX_DragOperationNone);
  246. }
  247.  
  248. - (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
  249. {
  250.   return YES;
  251. }
  252.  
  253. - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
  254. {
  255.     Pasteboard *pboard = [sender draggingPasteboard];
  256.  
  257.     if (includesType([pboard types], NXColorPboardType))
  258.       {
  259.     NXColor color = NXReadColorFromPasteboard(pboard);
  260.     [[self window] setBackgroundColor:color];
  261.     [self display];  // reflect color change
  262.     return YES;
  263.       }
  264.     else
  265.       return NO;
  266. }
  267.  
  268. - concludeDragOperation:(id <NXDraggingInfo>)sender
  269. {
  270.   // Return value ignored.
  271.   return nil;
  272. }
  273.  
  274. @end
  275.